package BehavioralPattern.Visitor;

import BehavioralPattern.Visitor.element.Employee;
import BehavioralPattern.Visitor.visitor.ConcreteShowVisitor;
import BehavioralPattern.Visitor.visitor.ConcreteTotalVisitor;
import BehavioralPattern.Visitor.visitor.ShowVisitor;
import BehavioralPattern.Visitor.visitor.TotalVisitor;

import java.util.List;

/**
 * @Classname : VisitorClient
 * @Description : 测试 访问者模式
 * 行为型——访问者模式
 * 一、模式定义
 *   Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new
 *   operation without changing the classes of the elements on which it operates.
 *   封装一些作用于某种数据结构中的各元素的操作，它可以在不改变数据结义作用于这些元素的新的操作。
 *   优点：
 *      ① 符合单一职责，元素负责数据加载，访问者负责业务操作，不同职责分离，各自演绎变化
 *      ② 业务操作便于扩展，增加新的业务操作只需再创建一个访问者
 *      ③ 灵活性高，可以遍历不同类或接口，并对其进行个性的处理操作（如汇总报表中普通员工和管理者的薪资系数不同）
 *   缺点：
 *      ① 访问者依赖具体元素，违反依赖倒置原则
 *      ② 元素数据不易扩展，当元素中成员变量变化，所有的访问者都要修改
 * 二、模式类图
 *    https://kdocs.cn/l/csHbEtko7Adr
 * 三、适用场景
 *   1、一个对象结构包含很多不同的类，想对其实施很多不同的且依赖于具体类的操作时可使用访问者模式，从而避免污染这
 *   些类（如果不使用访问者模式则需要在这些类上修改以支持需要的新的操作）
 * 四、应用举例
 *   1、数据报表
 *   2、拦截器
 * @Author : chentianyu
 * @Date 2023/3/12 11:26
 */


public class VisitorClient {
    public static void main(String[] args) {
        System.out.println("------访问者模式------");
        // 创建展示报表访问者
        ShowVisitor showVisitor = new ConcreteShowVisitor();
        // 创建汇总报表访问者
        TotalVisitor totalVisitor = new ConcreteTotalVisitor();
        // 结构对象生产元素
        List<Employee> employeeList = ObjectStructure.createElement();
        // 报表处理
        for (Employee employee : employeeList) {
            employee.accept(showVisitor);  // 展示报表访问
            employee.accept(totalVisitor);  // 汇总报表访问
        }
        // 展示报表
        showVisitor.report();
        // 汇总报表
        totalVisitor.totalSalary();
    }
}

/** 20230312
 * ------访问者模式------
 * 姓名：张三	性别：男	薪资：1800	工作：编写程序，搬砖苦工
 * 姓名：李四	性别：女	薪资：1900	工作：设计页面，搬砖苦工
 * 姓名：王五	性别：男	薪资：18750	业绩：没有业绩，向上管理
 * 本公司的月工资总额是：101150
 */
